#include "./BSP/BEEP/beep_music_manager.h"
#include <stdio.h>

/* -------------------------------------------- 全局变量定义 -------------------------------------------- */

static music_player_t s_musicPlayers[MUSIC_PLAYER_MAX_NUM];    /* 音乐播放器数组 */

/* 时间计数最大值 */
#define TIME_MAX_VAL (uint32_t)0xffff
/* 时间累加宏,防止溢出 */
#define TIME_ADD(tic, time) (TIME_MAX_VAL - (tic) < (time) ? ((tic) = 0xffff) : (tic += time))

/* ----------------------------------------------- 乐谱定义 -------------------------------------------- */
/* 《生日快乐》 */
static const music_note_t happy_birthday[] = {
    {M5, 300}, {M5, 300}, {M6, 600}, {M5, 600}, {H1, 600}, {M7, 1000},
    {M5, 300}, {M5, 300}, {M6, 600}, {M5, 600}, {H2, 600}, {H1, 1000},
    {NOTE_REST, 0} /* 结束标志 */
};

/* 《起风了》 */
static const music_note_t wind_rise[] = {
    /* 前奏 */
    {L7, 125}, {M1, 125}, {M2, 125}, {M3, 125}, {L3, 250}, {M5, 125}, {M3, 125}, {M3, 250}, {NOTE_REST, 750},
    {L7, 125}, {M1, 125}, {M2, 125}, {M3, 125}, {L2, 250}, {M5, 125}, {M3, 125}, {M2, 125}, {M3, 125}, {M1, 125}, {M2, 125}, {L7, 125}, {M1, 125}, {L5, 125}, {NOTE_REST, 125},
    {L7, 125}, {M1, 125}, {M2, 125}, {M3, 125}, {L3, 250}, {M5, 125}, {M3, 375}, {NOTE_REST, 750},
    {L7, 125}, {M1, 125}, {M2, 125}, {M3, 125}, {L2, 250}, {M5, 125}, {M3, 125}, {M2, 125}, {M3, 125}, {M1, 125}, {M2, 125},
    
    /* 这一路上走走停停 顺着少年漂流的痕迹 */
    {M2, 250}, {M2, 250}, {M1, 225}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M3, 250}, {M5, 250}, {M3, 250},
    {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M3, 250}, {M2, 250}, {M1, 250}, {L6, 500},
    
    /* 迈出车站的前一刻 竟有些犹豫 */
    {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M3, 250}, {M5, 250}, {M3, 250},
    {M2, 250}, {M2, 250}, {M3, 125}, {M2, 250}, {M1, 250}, {M2, 500},
    
    /* 不仅笑着这近乡情怯 仍无法避免 */
    {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M3, 250}, {M5, 250}, {M3, 250},
    {M2, 250}, {M2, 250}, {M3, 125}, {M2, 250}, {M1, 250}, {L6, 500},
    
    /* 而长野的天 依旧那么暖 风吹起了从前 */
    {M3, 125}, {M2, 125}, {M1, 125}, {M2, 125}, {M1, 500},
    {M3, 125}, {M2, 125}, {M1, 125}, {M2, 125}, {M1, 250}, {M1, 250},
    {M5, 125}, {M3, 125}, {M2, 125}, {M1, 125}, {M2, 125}, {M1, 500}, {M1, 750},
    
    /* 从前初识这世间 万般留恋 看着天边似在眼前 也甘愿赴汤蹈火去走它一遍 */
    {M1, 250}, {M2, 250}, {M3, 250}, {M1, 250}, {M6, 250}, {M5, 125}, {M6, 125}, {M6, 250}, {M6, 250},
    {M1, 125}, {M7, 250}, {M6, 125}, {M7, 125}, {M7, 500}, {NOTE_REST, 25},
    {M7, 250}, {M6, 125}, {M7, 125}, {M7, 250}, {M3, 250}, {H1, 125}, {H2, 125}, {H1, 125}, {M7, 125}, {M6, 250}, {M5, 250},
    {M6, 250}, {M5, 125}, {M6, 125}, {M6, 125}, {M5, 125}, {M6, 125}, {M5, 125}, {M6, 250}, {M5, 125}, {M2, 125}, {M2, 125}, {M5, 250}, {M5, 250}, {M3, 500}, {M3, 500},
    
    /* 如今走过这世间 万般留恋 翻过岁月不同侧脸 措不及防闯入你的笑颜 */
    {M1, 250}, {M2, 250}, {M3, 250}, {M1, 250}, {M6, 250}, {M5, 125}, {M6, 125}, {M6, 250}, {M6, 250},
    {M1, 125}, {M7, 250}, {M6, 125}, {M7, 125}, {M7, 500}, {NOTE_REST, 25},
    {M7, 250}, {M6, 125}, {M7, 125}, {M7, 250}, {M3, 250}, {H1, 125}, {H2, 125}, {H1, 125}, {M7, 125}, {M6, 250}, {M5, 250},
    {M6, 250}, {H3, 125}, {H3, 125}, {H3, 250}, {M5, 250}, {M6, 250}, {H3, 125}, {H3, 125}, {H3, 125}, {M5, 250}, {M6, 125}, {M6, 500}, {M6, 500}, {M6, 500},
    
    /* 我曾难自拔于世界之大 也沉溺于其中梦话 */
    {H1, 250}, {H2, 250}, {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H2, 125}, {H3, 125}, {H3, 250},
    {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 125}, {H3, 250}, {H3, 250},
    
    /* 不得真假 不做挣扎 不惧笑话 */
    {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H1, 250},
    {M6, 125}, {H2, 125}, {H1, 125}, {M6, 250}, {M6, 125}, {H1, 250}, {H1, 250},
    {H3, 500}, {H3, 125}, {H4, 125}, {H3, 250}, {H3, 125}, {H2, 250}, {H2, 250},
    
    /* 我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动且就随缘去吧 */
    {H1, 250}, {H2, 250}, {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H2, 250},
    {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H3, 250}, {H3, 250},
    {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H3, 250}, {H3, 250},
    {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H1, 250}, {H1, 250}, {H1, 500}, {H1, 500},
    
    /* 短短的路走走停停 也有了几分的距离 */
    {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M3, 250}, {M5, 250}, {M3, 250},
    {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 125}, {M3, 125}, {M2, 125}, {M1, 125}, {L6, 500},
    
    /* 不知抚摸的是故事还是段心情 */
    {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M3, 250}, {M5, 250}, {M3, 250},
    {M2, 250}, {M2, 250}, {M3, 125}, {M2, 250}, {M1, 250}, {M2, 500},
    
    /* 也许期待的不过是与时间为敌 */
    {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M2, 250}, {M1, 125}, {M2, 250}, {M3, 250}, {M5, 250}, {M3, 250},
    {M2, 250}, {M2, 250}, {M3, 125}, {M2, 250}, {M1, 250}, {L6, 500},
    
    /* 再次见到你 微凉晨光里 笑的很甜蜜 */
    {M3, 125}, {M2, 125}, {M1, 125}, {M2, 125}, {M1, 500},
    {M3, 125}, {M2, 125}, {M1, 125}, {M2, 125}, {M1, 250}, {M1, 250},
    {M5, 125}, {M3, 125}, {M2, 125}, {M1, 125}, {M2, 125}, {M1, 500}, {M1, 750},
    
    /* 从前初识这世间 万般留恋 看着天边似在眼前 也甘愿赴汤蹈火去走它一遍 */
    {M1, 250}, {M2, 250}, {M3, 250}, {M1, 250}, {M6, 250}, {M5, 125}, {M6, 125}, {M6, 250}, {M6, 250},
    {M1, 125}, {M7, 250}, {M6, 125}, {M7, 125}, {M7, 500}, {NOTE_REST, 25},
    {M7, 250}, {M6, 125}, {M7, 125}, {M7, 250}, {M3, 250}, {H1, 125}, {H2, 125}, {H1, 125}, {M7, 125}, {M6, 250}, {M5, 250},
    {M6, 250}, {M5, 125}, {M6, 125}, {M6, 125}, {M5, 125}, {M6, 125}, {M5, 125}, {M6, 250}, {M5, 125}, {M2, 125}, {M2, 125}, {M5, 250}, {M5, 250}, {M3, 500}, {M3, 500},
    
    /* 如今走过这世间 万般留恋 翻过岁月不同侧脸 措不及防闯入你的笑颜 */
    {M1, 250}, {M2, 250}, {M3, 250}, {M1, 250}, {M6, 250}, {M5, 125}, {M6, 125}, {M6, 250}, {M6, 250},
    {M1, 125}, {M7, 250}, {M6, 125}, {M7, 125}, {M7, 500}, {NOTE_REST, 25},
    {M7, 250}, {M6, 125}, {M7, 125}, {M7, 250}, {M3, 250}, {H1, 125}, {H2, 125}, {H1, 125}, {M7, 125}, {M6, 250}, {M5, 250},
    {M6, 250}, {H3, 125}, {H3, 125}, {H3, 250}, {M5, 250}, {M6, 250}, {H3, 125}, {H3, 125}, {H3, 125}, {M5, 250}, {M6, 125}, {M6, 500}, {M6, 500}, {M6, 500},
    
    /* 我曾难自拔于世界之大 也沉溺于其中梦话 */
    {H1, 250}, {H2, 250}, {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H2, 125}, {H3, 125}, {H3, 250},
    {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 125}, {H3, 250}, {H3, 250},
    
    /* 不得真假 不做挣扎 不惧笑话 */
    {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H1, 250},
    {M6, 125}, {H2, 125}, {H1, 125}, {M6, 250}, {M6, 125}, {H1, 250}, {H1, 250},
    {H3, 500}, {H3, 125}, {H4, 125}, {H3, 250}, {H3, 125}, {H2, 250}, {H2, 250},
    
    /* 我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动且就随缘去吧 */
    {H1, 250}, {H2, 250}, {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H2, 250},
    {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H3, 250}, {H3, 250},
    {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H3, 250}, {H3, 250},
    {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H1, 250}, {H1, 250}, {H1, 500}, {H1, 500},
    
    /* 逆着光行走任风吹雨打吧 */
    {M6, 125}, {H3, 250}, {H3, 250}, {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H3, 250}, {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H1, 250}, {H1, 250}, {H1, 250}, {H1, 500},
    
    /* 晚风吹起你鬓间的白发 抚平回忆留下的疤 */
    {H1, 250}, {H2, 250}, {H2, 125}, {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H2, 125},
    {H3, 125}, {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 125}, {H3, 250}, {H3, 250},
    
    /* 你的眼中明暗交杂 一笑生花 暮色遮住你蹒跚的步伐 */
    {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H1, 250}, {M6, 125}, {H2, 125}, {H1, 125}, {M6, 250}, {M6, 250},
    {H1, 250}, {H1, 250}, {H3, 500}, {H3, 125}, {H4, 125}, {H3, 250}, {H3, 125}, {H2, 250}, {H2, 250}, {H1, 500}, {H2, 500}, {H3, 500}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H2, 250},
    
    /* 走进床头藏起的画 画中的你(低着头说话) */
    {H3, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H6, 125}, {H5, 125}, {H5, 250}, {H3, 500}, {H3, 250}, {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H3, 250}, {H3, 250}, {H2, 250}, {H1, 125}, {M6, 125}, {M6, 125}, {H1, 500}, {H1, 250},
    
    /* 我仍 了 以爱之名你还愿意吗（衔接头有问题） */
    {H1, 250}, {H2, 250}, {H1, 250}, {H1, 500}, {M6, 125}, {H3, 250}, {H3, 250}, {H2, 250}, {H1, 125}, {H6, 125}, {H6, 125}, {H3, 250}, {H3, 250}, {H2, 250}, {H1, 125}, {H6, 125}, {H6, 125}, {H1, 250}, {H1, 250}, {H1, 500}
};

/* -------------------------------------------- 音乐播放器初始化 -------------------------------------------- */

/**
 * @brief       初始化音乐播放器
 * @param       无
 * @retval      无
 */
static void InitMusicPlayers(void)
{
    for (uint8_t i = 0; i < MUSIC_PLAYER_MAX_NUM; i++)
    {
        s_musicPlayers[i].melody = NULL;
        s_musicPlayers[i].total_notes = 0;
        s_musicPlayers[i].current_note = 0;
        s_musicPlayers[i].note_duration = 0;
        s_musicPlayers[i].state = MUSIC_STATE_IDLE;
        s_musicPlayers[i].volume = 50;
        s_musicPlayers[i].loop = 0;
        s_musicPlayers[i].tic = 0;
    }
}

/* -------------------------------------------- 音乐播放器扫描函数 -------------------------------------------- */

/**
 * @brief   音乐播放状态扫描（非阻塞）
 * @note    需周期性调用，支持Tick溢出安全，支持多播放器并发
 * @param   sysTime 当前系统Tick（ms）
 */
void MUSIC_Scan(uint32_t sysTime)
{
    static uint32_t s_sysTimeBak = 0; /* 上次调用时的系统时间 */
    
    /* 首次调用,初始化时间 */
    if (s_sysTimeBak == 0)
    {
        s_sysTimeBak = sysTime;
        return;
    }
    
    for (uint8_t i = 0; i < MUSIC_PLAYER_MAX_NUM; i++)
    {
        music_player_t *player = &s_musicPlayers[i];
        
        /* 检查播放器是否处于播放状态 */
        if (player->state != MUSIC_STATE_PLAYING)
        {
            continue;
        }
        
        /* 推进tic，防止Tick溢出，累计当前音符已播放时长 */
        TIME_ADD(player->tic, (sysTime - s_sysTimeBak));
        
        /* 判断当前音符是否播放完成 */
        if (player->tic >= player->note_duration)
        {
            player->tic = 0; /* 重置tic，准备播放下一个音符 */
            player->current_note++;
            
            /* 检查是否到达乐谱结尾 */
            if (player->current_note >= player->total_notes)
            {
                if (player->loop)
                {
                    player->current_note = 0; /* 循环播放，回到开头 */
                }
                else
                {
                    player->state = MUSIC_STATE_IDLE; /* 播放完成，设为IDLE */
                    beep_stop();
                    continue;
                }
            }
            
            /* 获取当前音符 */
            const music_note_t *note = &player->melody[player->current_note];
            printf("[MUSIC] 切换到音符%d, 频率=%.2f, 时长=%d, tic=%lu, sysTime=%lu\r\n", \
                player->current_note, note->frequency, note->duration, player->tic, sysTime);
            
            if (note->frequency == NOTE_REST)
            {
                beep_stop(); /* 休止符，停止蜂鸣器 */
            }
            else
            {
                beep_set_frequency(note->frequency); /* 设置频率 */
                beep_set_volume(player->volume);     /* 设置音量 */
                beep_start();                        /* 启动蜂鸣器 */
            }
            player->note_duration = note->duration; /* 更新当前音符时长 */
        }
    }
    
    /* 保存这次的系统时间 */
    s_sysTimeBak = sysTime;
}

/* -------------------------------------------- 音乐播放控制函数 -------------------------------------------- */

/**
 * @brief       开始播放音乐
 * @param       player_id: 播放器ID
 * @param       melody: 音符数组
 * @param       note_count: 音符数量
 * @param       volume: 音量 (0-100)
 * @param       loop: 循环播放标志
 * @retval      无
 */
void MUSIC_Play(music_player_id_e player_id, const music_note_t *melody, uint16_t note_count, uint8_t volume, uint8_t loop)
{
    if (player_id >= MUSIC_PLAYER_MAX_NUM || melody == NULL || note_count == 0)
    {
        return;
    }
    
    music_player_t *player = &s_musicPlayers[player_id];
    
    /* 停止当前播放 */
    beep_stop();
    
    /* 初始化播放器 */
    player->melody = melody;
    player->total_notes = note_count;
    player->current_note = 0;
    player->volume = volume;
    player->loop = loop;
    player->state = MUSIC_STATE_PLAYING;
    player->tic = 0;
    
    /* 设置第一个音符的时长 */
    player->note_duration = melody[0].duration;
    
    /* 开始播放第一个音符 */
    const music_note_t *note = &melody[0];
    if (note->frequency == NOTE_REST)
    {
        beep_stop();
    }
    else
    {
        beep_set_frequency(note->frequency);
        beep_set_volume(volume);
        beep_start();
    }
}

/**
 * @brief       停止音乐播放
 * @param       player_id: 播放器ID
 * @retval      无
 */
void MUSIC_Stop(music_player_id_e player_id)
{
    if (player_id >= MUSIC_PLAYER_MAX_NUM)
    {
        return;
    }
    
    music_player_t *player = &s_musicPlayers[player_id];
    
    beep_stop();
    player->state = MUSIC_STATE_STOPPED;
    player->current_note = 0;
    player->tic = 0;
}

/**
 * @brief       暂停音乐播放
 * @param       player_id: 播放器ID
 * @retval      无
 */
void MUSIC_Pause(music_player_id_e player_id)
{
    if (player_id >= MUSIC_PLAYER_MAX_NUM)
    {
        return;
    }
    
    music_player_t *player = &s_musicPlayers[player_id];
    
    if (player->state == MUSIC_STATE_PLAYING)
    {
        beep_stop();
        player->state = MUSIC_STATE_PAUSED;
    }
}

/**
 * @brief       恢复音乐播放
 * @param       player_id: 播放器ID
 * @retval      无
 */
void MUSIC_Resume(music_player_id_e player_id)
{
    if (player_id >= MUSIC_PLAYER_MAX_NUM)
    {
        return;
    }
    
    music_player_t *player = &s_musicPlayers[player_id];
    
    if (player->state == MUSIC_STATE_PAUSED)
    {
        player->state = MUSIC_STATE_PLAYING;
        /* 恢复播放时不需要重置tic，保持暂停时的进度 */
    }
}

/* -------------------------------------------- 音乐播放状态查询函数 -------------------------------------------- */

/**
 * @brief       获取音乐播放状态
 * @param       player_id: 播放器ID
 * @retval      播放状态
 */
music_state_e MUSIC_GetState(music_player_id_e player_id)
{
    if (player_id >= MUSIC_PLAYER_MAX_NUM)
    {
        return MUSIC_STATE_IDLE;
    }
    
    return s_musicPlayers[player_id].state;
}

/**
 * @brief       检查是否正在播放
 * @param       player_id: 播放器ID
 * @retval      1:正在播放 0:未播放
 */
uint8_t MUSIC_IsPlaying(music_player_id_e player_id)
{
    return (MUSIC_GetState(player_id) == MUSIC_STATE_PLAYING);
}

/* -------------------------------------------- 预设音乐播放函数 -------------------------------------------- */

/**
 * @brief       播放生日快乐歌
 * @param       player_id: 播放器ID
 * @param       volume: 音量 (0-100)
 * @retval      无
 */
void MUSIC_PlayHappyBirthday(music_player_id_e player_id, uint8_t volume)
{
    MUSIC_Play(player_id, happy_birthday, sizeof(happy_birthday)/sizeof(happy_birthday[0]), volume, 0);
}

/**
 * @brief       播放《起风了》完整版
 * @param       player_id: 播放器ID
 * @param       volume: 音量 (0-100)
 * @retval      无
 */
void MUSIC_PlayWindRise(music_player_id_e player_id, uint8_t volume)
{
    MUSIC_Play(player_id, wind_rise, sizeof(wind_rise)/sizeof(wind_rise[0]), volume, 0);
}

/* -------------------------------------------- 音乐模块API函数 -------------------------------------------- */

/**
 * @brief       音乐播放器初始化函数
 * @param       无
 * @retval      无
 */
void FML_MUSIC_Init(void)
{
    InitMusicPlayers();
} 
